package br.com.contil.lid.dao;

import java.util.*;

import javax.persistence.*;
import javax.persistence.criteria.*;

import br.com.contil.lid.jpa.*;

public abstract class BaseDAO <T, K> {
	
	private final EntityManager entityManager;
	private final Class<T> entityClass;
	private final CriteriaBuilder builder;
	
	private CriteriaQuery<T> query;
	private Root<T> root;
	List<Predicate> predicates;
	
	public BaseDAO(Class<T> entityClass) {
		this.entityClass = entityClass;
		
		this.entityManager = LidEntityManagerFactory.getDefaultFactory().createEntityManager();
		this.builder = entityManager.getCriteriaBuilder();
	}
	
	protected final CriteriaQuery<T> getQuery() {
		if(query == null) {
			newQuery();
		}
		return query;
	}

	private final void setQuery(CriteriaQuery<T> query) {
		this.query = query;
	}
	
	protected final Root<T> getRoot() {
		if(root == null){
			newQuery();
		}
		
		return root;
	}

	private final void setRoot(Root<T> root) {
		this.root = root;
	}

	protected final List<Predicate> getPredicates() {
		if(predicates == null) {
			newQuery();
		}
		
		return predicates;
	}

	private final void setPredicates(List<Predicate> predicates) {
		this.predicates = predicates;
	}
	
	protected final void addPredicate(Predicate predicate) {
		getPredicates().add(predicate);
	}

	protected final EntityManager getEntityManager() {
		return entityManager;
	}

	protected final Class<T> getEntityClass() {
		return entityClass;
	}

	protected final CriteriaBuilder getBuilder() {
		return builder;
	}
	
	public final T findById(K id){
		return entityManager.find(entityClass, id);
	}
	
	public final void newQuery(){
		setQuery(builder.createQuery(entityClass));
		setRoot(query.from(entityClass));
		setPredicates(new ArrayList<Predicate>());
	}
	
	public final List<T> find() {
		query = query.where((Predicate[])predicates.toArray());
		return entityManager.createQuery(query).getResultList();
	}
	
}
